package logic;

import java.util.List;
import java.util.Random;

/**
 * A class representing shared characteristics of plants.
 * 
 * @author Vossen en Konijnen group 2
 */
public abstract class Plant implements Actor
{
    // A shared random number generator to control breeding.
    private static final Random rand = Randomizer.getRandom();
    // Whether the animal is alive or not.
    private boolean alive;
    // The animal's field.
    private Field field;
    // The animal's position in the field.
    private Location location;
    // The animal's age.
    protected int age;
    
    /**
     * Create a new plant at location in field.
     * 
     * @param field The field currently occupied.
     * @param location The location within the field.
     */
    public Plant(Field field, Location location)
    {
        alive = true;
        this.field = field;
        setLocation(location);
        age = 0;
    }
    
    /**
     * Make this plant act - that is: make it do
     * whatever it wants/needs to do.
     * @param newAnimals A list to add newly born plants to.
     */
    abstract public void act(List<Actor> newPlants);

    /**
     * Check whether the plant is alive or not.
     * @return true if the plant is still alive.
     */
    
    public boolean isAlive()
    {
        return alive;
    }
    
    public boolean isActive()
    {
    	return alive;
    }

    /**
     * Indicate that the plant is no longer alive.
     * It is removed from the field.
     */
    public void setDead()
    {
        alive = false;
        if(location != null) {
            field.clear(location);
            location = null;
            field = null;
        }
    }

    /**
     * Return the plant's location.
     * @return The plant's location.
     */
    public Location getLocation()
    {
        return location;
    }
    
    /**
     * Return the plant's field.
     * @return The plant's field.
     */
    public Field getField()
    {
        return field;
    }
    
    /**
     * Place the plant at the new location in the given field.
     * @param newLocation The plant's new location.
     */
    public void setLocation(Location newLocation)
    {
        if(location != null) {
            field.clear(location);
        }
        location = newLocation;
        field.place(this, newLocation);
    }
    
    /**
     * Sets the age of the plant
     * @param maxage
     */
    
    protected void setAge()
    {
    	age = rand.nextInt(getMaxAge());
    }
    
    /**
     * Returns the age of the plant
     * @return
     */
    protected int getAge()
    {
    	return age;
    }
    /**
     * Increase the age. This could result in the plant's death.
     */
    protected void incrementAge()
    {
        age++;
        if(age > getMaxAge()) {
            setDead();
        }
    }
    
    /**
     * A plant can grow if it has reached the breeding age.
     * @return true if the plant is able to breed.
     */
    protected boolean canGrow()
    {
        return age >= getGrowingAge();
    }
    
    /**
     * Returns the breeding age of this plant
     * @return The breeding age of this plant
     */
    protected abstract int getGrowingAge();
    
    /**
     * Returns the maximum age of this plant
     * @return The maximum age of this plant
     */
    protected abstract int getMaxAge();
    /**
     * Generate a number representing the number of births,
     * if it can breed.
     * @return The number of births (may be zero).
     */
    protected int grow()
    {
        int smallPlants = 0;
        if(canGrow() && rand.nextDouble() <= getGrowingProbability()) {
        	smallPlants = rand.nextInt(getMaxLitterSize()) + 1;
        }
        return smallPlants;
    }
    
    /**
     * Check whether or not this plant is to give birth at this step.
     * New births will be made into free adjacent locations.
     * @param newPlants A list to add newly born plant to.
     * @param name A String which provides the type of animal being born
     */
    protected void growPlant(List<Actor> newPlants, String name)
    {
        // New rabbits are born into adjacent locations.
        // Get a list of adjacent free locations.
        Field field = getField();
        List<Location> free = field.getFreeAdjacentLocations(getLocation());
        int smallPlants = grow();
        for(int b = 0; b < smallPlants && free.size() > 0; b++) {
            Location loc = free.remove(0);
            
            Plant young = newPlant(field, loc);
            
            newPlants.add(young);
        }
    }
    /**
     * Returns the likelihood of this plant to reproduce
     * @return BREEDING_PROBABILITY of this plant
     */
    protected abstract double getGrowingProbability();
    
    /**
     * Returns the maximum number of births of this plant
     * @return MAX_LITTER_SIZE of this plant
     */
    protected abstract int getMaxLitterSize();

    /**
     * Returns the newPlant class
     * @return the newPlant class
     */
    protected abstract Plant newPlant(Field field, Location location);
}



